package com.demo.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.demo.mapper.StudentMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import redis.clients.jedis.Jedis;

import java.util.*;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;

public class DelayTaskConsumer extends Thread {
    private Log log = LogFactory.getLog(this.getClass());

    private final DelayQueue<Item> queue;
    private final ExecutorService executorService;
    private final String key;
    private final StudentMapper studentMapper;
    private final Jedis redis;
    private List<Map<String, String>> studentAnswerList = new ArrayList<>();


    public DelayTaskConsumer(DelayQueue<Item> queue, ExecutorService executorService, StudentMapper studentMapper, Jedis redis, String key) {
        this.queue = queue;
        this.executorService = executorService;
        this.studentMapper = studentMapper;
        this.redis = redis;
        this.key = key;
    }

    @Override
    public void run() {
        Item task = null;
        try {
            while (true) {
                task = queue.take();
                /**
                 * 创建班级学生作答记录表
                 * 存储班级学生作答记录
                 */
                createStudentAnswerBank();
                /**
                 * 计算学生考试成绩
                 */
                calcStudentExaminationResult();
                log.info(task.toString());
            }
        } catch (InterruptedException e) {
            log.error(getName() + " finished.");
        } finally {
            executorService.shutdown();
        }
    }

    // 创建学生作答记录表，同时添加学生作答信息
    public void createStudentAnswerBank() {
        Set<String> hkeys = redis.hkeys(key);
        //List<Map<String, String>> list = new ArrayList<>();
        for (String str : hkeys) {
            Map<String, String> map = new HashMap<>();
            map.put("studentNumber", str);
            map.put("rightOption", redis.hget(key, str));
            studentAnswerList.add(map);
        }
        if (studentAnswerList.isEmpty()) return;
        studentMapper.createStudentAnswerBank(key, studentAnswerList);
    }

    //匹配 试题库与作答库 中每一位学生的答案，并统计分数。完成数据的批量更新
    public void calcStudentExaminationResult() {
        String classNumber = key.substring(0, key.indexOf("-"));
        String questionBank = key.substring(key.indexOf("-") + 1);
        List<Map<String, String>> answersToQuestionBank = studentMapper.getAnswersToQuestionBank(questionBank);

        Map<String, String> class_course = new HashMap<>();
        class_course.put("classNumber", classNumber);
        class_course.put("coursesName", answersToQuestionBank.get(0).get("coursesName"));

        List<Map<String, String>> result = new ArrayList<>();
        for (int i = 0; i < studentAnswerList.size(); i++) {
            Map<String, String> student = new HashMap<>();
            student.put("studentNumber", studentAnswerList.get(i).get("studentNumber"));
            student.put("score", "0");

            JSONArray jsonArray = JSON.parseArray(studentAnswerList.get(i).get("rightOption"));
            for (int j = 0; j < jsonArray.size(); j++) {
                JSONArray jsonArray1 = JSON.parseArray(jsonArray.get(j).toString());
                for (int s = 0; s < answersToQuestionBank.size(); s++) {
                    /**
                     * 以下判断主要功能，学生作答记录中的试题编号去匹配试题库中的试题编号
                     * 存在，则根据继续下一步判断
                     * 反之，则学生没有作答本试题
                     */
                    if (jsonArray1.get(0).equals(answersToQuestionBank.get(s).get("id"))) {
                        /**
                         * 以下选择主要功能，匹配与之试题类型对应的算法
                         */
                        switch (answersToQuestionBank.get(s).get("type")) {
                            case "radio":
                                this.calcAnswerList_radio(jsonArray1, answersToQuestionBank.get(s), student);
                                break;
                            case "checkbox":
                                this.calcAnswerList_checkbox(jsonArray1, answersToQuestionBank.get(s), student);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            result.add(student);
        }
        try {
            studentMapper.updateStudentExaminationResult(class_course, result);
            DelayTaskConsumer.deleteRedisClassExamination(redis, classNumber, questionBank,
                    answersToQuestionBank.get(0).get("coursesName"), answersToQuestionBank.get(0).get("teacherNumber"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 单选题型计算
     *
     * @param jsonArray             学生作答答案数组
     * @param answersToQuestionBank 试题库
     * @param student               学生成绩
     */
    private void calcAnswerList_radio(JSONArray jsonArray, Map<String, String> answersToQuestionBank, Map<String, String> student) {
        if (jsonArray.getString(1).equals(answersToQuestionBank.get("rightOption"))) {
            float score = Float.parseFloat(student.get("score"));
            score += Float.parseFloat(String.valueOf(answersToQuestionBank.get("score")));
            student.put("score", String.valueOf(score));
        }
    }

    /**
     * 多选题型计算
     *
     * @param jsonArray             学生作答答案数组
     * @param answersToQuestionBank 试题库
     * @param student               学生成绩
     */
    private void calcAnswerList_checkbox(JSONArray jsonArray, Map<String, String> answersToQuestionBank, Map<String, String> student) {
        String[] studentAnswer = jsonArray.getString(1).split("&");
        String[] rightOptions = answersToQuestionBank.get("rightOption").split("&");
        /**
         * 学生答案个数与正确答案个数不等，则答案一定错误
         */
        if (studentAnswer.length != rightOptions.length) return;
        boolean flag = true;
        for (int i = 0; i < studentAnswer.length; i++) {
            if (!flag) {
                break;
            }
            for (int j = 0; j < rightOptions.length; j++) {
                if (studentAnswer[i].equals(rightOptions[j])) {
                    flag = true;
                    break;
                }
                flag = false;
            }
        }
        if (flag) {
            float score = Float.parseFloat(student.get("score"));
            score += Float.parseFloat(String.valueOf(answersToQuestionBank.get("score")));
            student.put("score", String.valueOf(score));
        }
    }

    /**
     * 删除redis中创建的班级考试记录 - 外部可调用
     *
     * @param redis         redis
     * @param classNumber   班级号
     * @param questionBank  试题库号
     * @param coursesName   课程名
     * @param teacherNumber 教师编号
     */
    public static void deleteRedisClassExamination(Jedis redis, String classNumber, String questionBank, String coursesName, String teacherNumber) {
        if (redis.exists(classNumber)) {
            JSONArray jsonArray = JSON.parseArray(redis.get(classNumber));
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = JSON.parseObject(jsonArray.getString(i));
                if (jsonObject.getString("questionBank") != null && jsonObject.getString("questionBank").equals(questionBank)) {
                    jsonArray.remove(i);
                    break;
                } else if (jsonObject.getString("questionBank") == null && jsonObject.getString("coursesName").equals(coursesName) && jsonObject.getString("teacherNumber").equals(teacherNumber)) {
                    jsonArray.remove(i);
                }
            }
            if (jsonArray.size() == 0) redis.del(classNumber);
        }
    }
}
